#ifndef PRYN_OBJECT_H
#define PRYN_OBJECT_H

typedef struct PrynObject PrynObject;
typedef struct PrynMonitorList PrynMonitorList;

/** @defgroup PrynObject PrynObject C API
@{ */

/** @brief A type of an object. */
enum PrynObjectType
{
	PrynObjectTypeNone = 0, ///< Not an object.
	PrynObjectTypePointer = 1, ///< General pointer to data.
	PrynObjectTypeString = 2, ///< PrynString value.

	PrynObjectTypeChange = 14, ///< PrynChange value.
	PrynObjectTypeComponent = 4, ///< PrynComponent value.
	PrynObjectTypeFactory = 5, ///< PrynFactory value.
	PrynObjectTypeLibrary = 6, ///< PrynLibrary value.
	PrynObjectTypeMediator = 7, ///< PrynMediator value.
	PrynObjectTypeMonitor = 8, ///< PrynMonitor value.
	PrynObjectTypePin = 9, ///< PrynPin value.
	PrynObjectTypeState = 3, ///< PrynState value.
	PrynObjectTypeStream = 14, ///< PrynStream value.
	PrynObjectTypeTag = 10, ///< PrynTag value.
	PrynObjectTypeType = 11, ///< PrynType value.
	PrynObjectTypeValue = 12, ///< PrynValue value.
	
	PrynObjectTypeGuiControl = 13, ///< PrynGuiControl value from the prynGui library.
	// next: 15
};

/** @brief An object reference. */
struct PrynObject
{
	PrynObjectType type; ///< Type of the contained object.
	void *pointer; ///< Pointer to the object.

#if __cplusplus
	inline PrynResult checkError (PrynResult result) { return prynCheckErrorBase (state (), result); } ///< If the result is below zero, throw an error.

	inline PrynState *state (); ///< The state the object is within or 0 if there is none for this object type.
	inline PrynTagList *tags (); ///< The list of tags associated with the object or 0 if there are none for this object type.
	inline PrynMonitorList *monitors (); ///< The list of monitors associated with the object or 0 if there are none for this object type.
#endif /* __cplusplus */
};

/** @} */ // (PrynObject group end, continued after includes)

#include <pryn/monitor.h>
#include <pryn/state.h>
#include <pryn/tag.h>

/** @addtogroup PrynObject
	@{ */

PrynImport (PrynResult, prynObjectState, (const PrynObject *object, PrynState **output)) ///< Retrieve the state the object is created in or 0 if there is none for this object type; returns #PrynResultFalse if there is no state.
PrynImport (PrynResult, prynObjectTags, (const PrynObject *object, PrynTagList **output)) ///< Return the list of tags associated with the object or 0 if there are none for this object type; returns #PrynResultFalse if there is no state.
PrynImport (PrynResult, prynObjectMonitors, (const PrynObject *object, PrynMonitorList **output)) ///< Return the list of monitors associated with the object or 0 if there are none for this object type.
PrynImport (PrynResult, prynObjectScope, (const PrynObject *object, PrynObject *scope)) ///< Retrieve the parent scope of this object. The parent scope of a pin is its component, then the factory, then the mediator (if any), then the library, then the state. This returns #PrynResultDone if there is no parent scope, as well as setting an object type of #PrynObjectTypeNone.

/** @} */ // (group)

#endif /* PRYN_OBJECT_H */
